home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / vm / ds3100.md / vmPmaxAsm.s < prev    next >
Text File  |  1990-09-11  |  23KB  |  981 lines

  1. /* vmPmaxAsm.s -
  2.  *
  3.  *    Subroutines to access PMAX virtual memory mapping hardware.
  4.  *
  5.  * Copyright (C) 1989 Digital Equipment Corporation.
  6.  * Permission to use, copy, modify, and distribute this software and
  7.  * its documentation for any purpose and without fee is hereby granted,
  8.  * provided that the above copyright notice appears in all copies.  
  9.  * Digital Equipment Corporation makes no representations about the
  10.  * suitability of this software for any purpose.  It is provided "as is"
  11.  * without express or implied warranty.
  12.  *
  13.  * $Header: /sprite/src/kernel/vm/ds3100.md/RCS/vmPmaxAsm.s,v 9.2 90/09/11 10:46:54 shirriff Exp $ SPRITE (DECWRL)
  14.  */
  15.  
  16. #include "vmPmaxConst.h"
  17. #include "machAsmDefs.h"
  18. #include <regdef.h>
  19.  
  20.  
  21. /*
  22.  *--------------------------------------------------------------------------
  23.  *
  24.  * VmMachWriteTLB --
  25.  *
  26.  *    Write the given entry into the TLB.
  27.  *
  28.  *    VmMachWriteTLB(lowEntry, highEntry)
  29.  *        unsigned    lowEntry;
  30.  *        unsigned    highEntry;
  31.  *
  32.  *    Results:
  33.  *        Returns the old index corresponding to the high register.
  34.  *
  35.  *    Side effects:
  36.  *        TLB entry set.
  37.  *
  38.  *--------------------------------------------------------------------------
  39.  */
  40. LEAF(VmMachWriteTLB)
  41. .set noreorder
  42.     mfc0    t0, VMMACH_TLB_HI    # Save the high register because this
  43.     nop                    #   contains the current PID.
  44.     mtc0    a1, VMMACH_TLB_HI    # Store into the high register.
  45.     nop
  46.     tlbp                # Probe for value.
  47.     mfc0    v0, VMMACH_TLB_INDEX    # See what index we got.  This value
  48.                     #   is returned as the result of this
  49.                     #   procedure.
  50.     mtc0    a0, VMMACH_TLB_LOW    # Set the low register.
  51.     nop
  52.     bltz    v0, 1f            # index < 0 means not found
  53.     nop
  54.     tlbwi                # Reuse the entry that we found
  55.     mtc0    t0, VMMACH_TLB_HI    # Restore the PID.
  56.     j        ra            
  57.     nop
  58. 1:  tlbwr                # Write a random entry.
  59.     mtc0    t0, VMMACH_TLB_HI    # Restore the PID
  60.     j        ra
  61.     nop
  62. .set reorder
  63. END(VmMachWriteTLB)
  64.  
  65.  
  66. /*
  67.  *--------------------------------------------------------------------------
  68.  *
  69.  * VmMachWriteIndexedTLB --
  70.  *
  71.  *    Write the given entry into the TLB at the given index.
  72.  *
  73.  *    VmMachWriteTLB(index, lowEntry, highEntry)
  74.  *        unsigned    index;
  75.  *        unsigned    lowEntry;
  76.  *        unsigned    highEntry;
  77.  *
  78.  *    Results:
  79.  *        None.
  80.  *
  81.  *    Side effects:
  82.  *        TLB entry set.
  83.  *
  84.  *--------------------------------------------------------------------------
  85.  */
  86. LEAF(VmMachWriteIndexedTLB)
  87. .set noreorder
  88.     mfc0    t0, VMMACH_TLB_HI    # Save the high register because this
  89.                     #   contains the current PID.
  90.  
  91.     sll        a0, a0, VMMACH_TLB_INDEX_SHIFT
  92.     mtc0    a0, VMMACH_TLB_INDEX    # Set the index.
  93.     mtc0    a1, VMMACH_TLB_LOW    # Set up entry low.
  94.     mtc0    a2, VMMACH_TLB_HI    # Set up entry high.
  95.     nop
  96.     tlbwi                # Write the TLB
  97.  
  98.     mtc0    t0, VMMACH_TLB_HI    # Restore the PID.
  99.  
  100.     j        ra
  101.     nop
  102. .set reorder
  103. END(VmMachWriteIndexedTLB)
  104.  
  105. /* 
  106.  *--------------------------------------------------------------------------
  107.  *
  108.  * VmMachFlushPIDFromTLB --
  109.  *
  110.  *    Flush all pages for the given PID from the TLB.
  111.  *
  112.  *    VmMachFlushPIDFromTLB(pid)
  113.  *        int        pid;
  114.  *
  115.  *    Results:
  116.  *        None.
  117.  *
  118.  *    Side effects:
  119.  *        All entries corresponding to this PID are flushed.
  120.  *
  121.  *--------------------------------------------------------------------------
  122.  */
  123. LEAF(VmMachFlushPIDFromTLB)
  124. .set noreorder
  125.     subu    sp, sp, STAND_FRAME_SIZE
  126.     sw        ra, STAND_RA_OFFSET(sp)
  127.     sw        a0, STAND_FRAME_SIZE(sp)
  128.     .mask    0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
  129.  
  130.     mfc0    t0, VMMACH_TLB_HI        # Save the PID
  131.     sll        a0, a0, VMMACH_TLB_PID_SHIFT    # Align the pid to flush.
  132.  
  133. /*
  134.  * Align the starting value (t1), the increment (t2) and the upper bound (t3).
  135.  */
  136.     li        t1, VMMACH_FIRST_RAND_ENTRY << VMMACH_TLB_INDEX_SHIFT
  137.     li        t2, 1 << VMMACH_TLB_INDEX_SHIFT
  138.     li        t3, VMMACH_NUM_TLB_ENTRIES << VMMACH_TLB_INDEX_SHIFT
  139.  
  140. 1:  mtc0    t1, VMMACH_TLB_INDEX        # Set the index register
  141.     addu    t1, t1, t2            # Increment index.
  142.     tlbr                    # Read from the TLB    
  143.     mfc0    t4, VMMACH_TLB_HI        # Fetch the hi register.
  144.     nop
  145.     and        t4, t4, a0            # See if the pids match.
  146.     bne        t4, a0, 2f
  147.     li        t4, VMMACH_PHYS_CACHED_START
  148.     mtc0    t4, VMMACH_TLB_HI        # Mark entry high as invalid
  149.     mtc0    zero, VMMACH_TLB_LOW        # Zero out entry low.
  150.     nop
  151.     tlbwi                    # Write the entry.
  152. 2:
  153.     bne        t1, t3, 1b
  154.     nop
  155.  
  156.     mtc0    t0, VMMACH_TLB_HI
  157.     addu    sp, sp, STAND_FRAME_SIZE
  158.  
  159.     j        ra
  160.     nop
  161. .set reorder
  162. END(VmMachFlushPIDFromTLB)
  163.  
  164.  
  165. /* 
  166.  *--------------------------------------------------------------------------
  167.  *
  168.  * VmMachFlushTLB --
  169.  *
  170.  *    Flush the TLB.
  171.  *
  172.  *    VmMachFlushTLB()
  173.  *
  174.  *    Results:
  175.  *        None.
  176.  *
  177.  *    Side effects:
  178.  *       The TLB is flushed.
  179.  *
  180.  *--------------------------------------------------------------------------
  181.  */
  182. LEAF(VmMachFlushTLB)
  183. .set noreorder
  184.     subu    sp, sp, STAND_FRAME_SIZE
  185.     sw        ra, STAND_RA_OFFSET(sp)
  186.     .mask    0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
  187.  
  188.     mfc0    t0, VMMACH_TLB_HI        # Save the PID
  189.     li        t1, VMMACH_PHYS_CACHED_START
  190.     mtc0    t1, VMMACH_TLB_HI        # Invalidate hi entry.
  191.     mtc0    zero, VMMACH_TLB_LOW        # Zero out entry low.
  192.  
  193. /*
  194.  * Align the starting value (t1), the increment (t2) and the upper bound (t3).
  195.  */
  196.     li        t1, VMMACH_FIRST_RAND_ENTRY << VMMACH_TLB_INDEX_SHIFT
  197.     li        t2, 1 << VMMACH_TLB_INDEX_SHIFT
  198.     li        t3, VMMACH_NUM_TLB_ENTRIES << VMMACH_TLB_INDEX_SHIFT
  199.  
  200. 1:  mtc0    t1, VMMACH_TLB_INDEX        # Set the index register.
  201.     addu    t1, t1, t2            # Increment index.
  202.     tlbwi                    # Write the TLB entry.
  203.     bne        t1, t3, 1b
  204.     nop
  205.  
  206.     mtc0    t0, VMMACH_TLB_HI        # Restore the PID
  207.     addu    sp, sp, STAND_FRAME_SIZE
  208.  
  209.     j        ra
  210.     nop
  211. .set reorder
  212. END(VmMachFlushTLB)
  213.  
  214.  
  215. /* 
  216.  *--------------------------------------------------------------------------
  217.  *
  218.  * VmMachFlushPageFromTLB --
  219.  *
  220.  *    Flush the given page from the TLB for the given process.
  221.  *
  222.  *    VmMachFlushPageFromTLB(pid, page)
  223.  *
  224.  *    Results:
  225.  *        None.
  226.  *
  227.  *    Side effects:
  228.  *       The process's page is flushed from the TLB.
  229.  *
  230.  *--------------------------------------------------------------------------
  231.  */
  232. LEAF(VmMachFlushPageFromTLB)
  233. .set noreorder
  234.     mfc0    t0, VMMACH_TLB_HI            # Save PID
  235.  
  236.     sll        a0, a0, VMMACH_TLB_PID_SHIFT        # Align pid
  237.     sll        a1, a1, VMMACH_TLB_VIRT_PAGE_SHIFT    # Align virt page
  238.     or        t1, a0, a1                # Set up entry.
  239.     mtc0    t1, VMMACH_TLB_HI            # Put into high reg.
  240.     nop
  241.     tlbp                        # Probe for the entry.
  242.     mfc0    v0, VMMACH_TLB_INDEX            # See what we got
  243.     li        t1, VMMACH_PHYS_CACHED_START        # Load invalid entry.
  244.     bltz    v0, 1f                    # index < 0 => !found
  245.     nop
  246.     mtc0    t1, VMMACH_TLB_HI            # Prepare index hi.
  247.     mtc0    zero, VMMACH_TLB_LOW            # Prepare index lo.
  248.     nop
  249.     tlbwi
  250.  
  251. 1:
  252.     mtc0    t0, VMMACH_TLB_HI            # Restore the PID
  253.     j        ra
  254.     nop
  255.  
  256. .set reorder
  257. END(VmMachFlushPageFromTLB)
  258.  
  259.  
  260. /* 
  261.  *--------------------------------------------------------------------------
  262.  *
  263.  * VmMachClearTLBModBit --
  264.  *
  265.  *    Clear the modified bit for the given <pid, page> pair.
  266.  *
  267.  *    VmMachClearTLBModBit(pid, page)
  268.  *
  269.  *    Results:
  270.  *        None.
  271.  *
  272.  *    Side effects:
  273.  *       The process's page is flushed from the TLB.
  274.  *
  275.  *--------------------------------------------------------------------------
  276.  */
  277. LEAF(VmMachClearTLBModBit)
  278. .set noreorder
  279.     mfc0    t0, VMMACH_TLB_HI            # Save PID
  280.  
  281.     sll        a0, a0, VMMACH_TLB_PID_SHIFT        # Align pid
  282.     sll        a1, a1, VMMACH_TLB_VIRT_PAGE_SHIFT    # Align virt page
  283.     or        t1, a0, a1                # Set up entry.
  284.     mtc0    t1, VMMACH_TLB_HI            # Put into high reg.
  285.     nop
  286.     tlbp                        # Probe for the entry.
  287.     mfc0    v0, VMMACH_TLB_INDEX            # See what we got
  288.     nop
  289.     bltz    v0, 1f                    # index < 0 => !found
  290.     nop
  291.     tlbr
  292.     mfc0    t1, VMMACH_TLB_LOW            # Read out low.
  293.     nop
  294.     and        t1, t1, ~VMMACH_TLB_MOD_BIT
  295.     mtc0    t1, VMMACH_TLB_LOW            # Write index low.
  296.     nop
  297.     tlbwi                        # Write the TLB entry.
  298.  
  299. 1:
  300.     mtc0    t0, VMMACH_TLB_HI            # Restore the PID
  301.     j        ra
  302.     nop
  303.  
  304. .set reorder
  305. END(VmMachClearTLBModBit)
  306.  
  307. #ifdef notdef
  308.  
  309. /* 
  310.  *--------------------------------------------------------------------------
  311.  *
  312.  * VmMachFlushGlobalPageFromTLB --
  313.  *
  314.  *    Flush the given page from the TLB for the given process.
  315.  *
  316.  *    VmMachFlushPageFromTLB(pid, page)
  317.  *
  318.  *    Results:
  319.  *        None.
  320.  *
  321.  *    Side effects:
  322.  *       The process's page is flushed from the TLB.
  323.  *
  324.  *--------------------------------------------------------------------------
  325.  */
  326. LEAF(VmMachFlushGlobalPageFromTLB)
  327. .set noreorder
  328.     subu    sp, sp, STAND_FRAME_SIZE
  329.     sw        ra, STAND_RA_OFFSET(sp)
  330.     .mask    0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
  331.  
  332.     mfc0    t0, VMMACH_TLB_HI            # Save PID
  333.  
  334.     sll        t1, a0, VMMACH_TLB_VIRT_PAGE_SHIFT    # Align virt page
  335.  
  336.     add        t2, zero, zero
  337.     li        t3, VMMACH_NUM_TLB_ENTRIES << VMMACH_TLB_INDEX_SHIFT
  338.     li        v0, 0x80000000
  339.  
  340. 6:  mtc0    t2, VMMACH_TLB_INDEX            # Set index
  341.     nop
  342.     tlbr                        # Read an entry.
  343.     mfc0    t4, VMMACH_TLB_HI
  344.     nop
  345.     and        t4, t4, VMMACH_TLB_VIRT_PAGE_NUM
  346.     bne        t4, t1, 2f                # test for pid/vpn match
  347.     nop
  348.  
  349.     add        v0, t2, zero
  350.     li        t4, VMMACH_PHYS_CACHED_START
  351.     mtc0    t4, VMMACH_TLB_HI            # Prepare index hi
  352.     mtc0    zero, VMMACH_TLB_LOW            # Prepare index lo
  353.     nop
  354.     tlbwi                        # Invalidate entry
  355. 2:
  356.     add        t2, t2, 1 << VMMACH_TLB_INDEX_SHIFT
  357.     bne        t2, t3, 6b
  358.     nop
  359.  
  360. 4:  mtc0    t0, VMMACH_TLB_HI    
  361.     addu    sp, sp, STAND_FRAME_SIZE
  362.     j        ra
  363.     nop
  364.  
  365. .set reorder
  366. END(VmMachFlushGlobalPageFromTLB)
  367. #endif
  368.  
  369. /* 
  370.  *--------------------------------------------------------------------------
  371.  *
  372.  * VmMachDumpTLB --
  373.  *
  374.  *    Flush the TLB.
  375.  *
  376.  *    VmMachFlushTLB(tlbPtr)
  377.  *        unsigned *tlbPtr;
  378.  *
  379.  *    Results:
  380.  *        None.
  381.  *
  382.  *    Side effects:
  383.  *       The contents of the TLB are written to *tlbPtr.
  384.  *
  385.  *--------------------------------------------------------------------------
  386.  */
  387. LEAF(Vm_MachDumpTLB)
  388. .set noreorder
  389.     subu    sp, sp, STAND_FRAME_SIZE
  390.     sw        ra, STAND_RA_OFFSET(sp)
  391.     .mask    0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
  392.  
  393.     mfc0    t0, VMMACH_TLB_HI        # Save the PID
  394.  
  395. /*
  396.  * Align the starting value (t1), the increment (t2) and the upper bound (t3).
  397.  */
  398.     li        t1, 0
  399.     li        t2, 1 << VMMACH_TLB_INDEX_SHIFT
  400.     li        t3, VMMACH_NUM_TLB_ENTRIES << VMMACH_TLB_INDEX_SHIFT
  401.  
  402. 1:  mtc0    t1, VMMACH_TLB_INDEX        # Set the index register.
  403.     addu    t1, t1, t2            # Increment index.
  404.     tlbr                    # Read the TLB entry.
  405.     mfc0    t4, VMMACH_TLB_LOW
  406.     mfc0    t5, VMMACH_TLB_HI
  407.     sw        t4, 0(a0)
  408.     sw        t5, 4(a0)
  409.     add        a0, a0, 8
  410.     bne        t1, t3, 1b
  411.     nop
  412.  
  413.     mtc0    t0, VMMACH_TLB_HI        # Restore the PID
  414.     addu    sp, sp, STAND_FRAME_SIZE
  415.  
  416.     j        ra
  417.     nop
  418. .set reorder
  419. END(Vm_MachDumpTLB)
  420.  
  421. /* 
  422.  *--------------------------------------------------------------------------
  423.  *
  424.  * VmMachSetPID --
  425.  *
  426.  *    Write the given pid into the TLB pid reg.
  427.  *
  428.  *    VmMachWritePID(pid)
  429.  *        int        pid;
  430.  *
  431.  *    Results:
  432.  *        None.
  433.  *
  434.  *    Side effects:
  435.  *        PID set in the entry hi register.
  436.  *
  437.  *--------------------------------------------------------------------------
  438.  */
  439.     .globl VmMachSetPID
  440. VmMachSetPID:
  441.     sll        a0, a0, 6        # Reg 4 <<= 6 to put PID in right spot
  442.     mtc0    a0, VMMACH_TLB_HI    # Write the hi reg value
  443.     j        ra
  444.  
  445.  
  446. /*
  447.  * ----------------------------------------------------------------------
  448.  *
  449.  * Vm_Copy{In,Out}
  450.  *
  451.  *    Copy numBytes from *sourcePtr in to *destPtr.
  452.  *    This routine is optimized to do transfers when sourcePtr and 
  453.  *    destPtr are both 4-byte aligned.
  454.  *
  455.  *    ReturnStatus
  456.  *    Vm_Copy{In,Out}(numBytes, sourcePtr, destPtr)
  457.  *        register int numBytes;      * The number of bytes to copy *
  458.  *        Address sourcePtr;          * Where to copy from. *
  459.  *        Address destPtr;            * Where to copy to. *
  460.  *
  461.  *    NOTE: The trap handler assumes that this routine does not push anything
  462.  *          onto the stack.  It uses this fact to allow it to return to the
  463.  *          caller of this routine upon an address fault.  If you must push
  464.  *          something onto the stack then you had better go and modify 
  465.  *          "CallTrapHandler" in asmDefs.h appropriately.
  466.  *
  467.  * Results:
  468.  *    Returns SUCCESS if the copy went OK (which is almost always).  If
  469.  *    a bus error (other than a page fault) occurred while reading or
  470.  *    writing user memory, then SYS_ARG_NO_ACCESS is returned (this return
  471.  *    occurs from the trap handler, rather than from this procedure).
  472.  *
  473.  * Side effects:
  474.  *    The area that destPtr points to is modified.
  475.  *
  476.  * ----------------------------------------------------------------------
  477.  */
  478.     .globl VmMachDoCopy
  479.     .globl Vm_CopyIn
  480. VmMachDoCopy:
  481. Vm_CopyIn:
  482. /*
  483.  * The number of bytes was passed in in r4, the source in r5, and the dest
  484.  * in r6.
  485.  *
  486.  * If the source or dest are not 4 byte aligned then everything must be
  487.  * done as byte copies.
  488.  */
  489.  
  490. gotArgs:
  491.     or        t0, a1, a2
  492.     andi    t0, t0, 3
  493.     blez    t0, 1f
  494.     j        3f
  495.  
  496. /*
  497.  * Do as many 64-byte copies as possible.
  498.  */
  499.  
  500. 1:
  501.     sub        t0, a0, 64
  502.     bltz    t0, 2f
  503.     lw        t0, 0(a1)
  504.     lw        t1, 4(a1)
  505.     sw        t0, 0(a2)
  506.     sw        t1, 4(a2)
  507.     lw        t0, 8(a1)
  508.     lw        t1, 12(a1)
  509.     sw        t0, 8(a2)
  510.     sw        t1, 12(a2)
  511.     lw        t0, 16(a1)
  512.     lw        t1, 20(a1)
  513.     sw        t0, 16(a2)
  514.     sw        t1, 20(a2)
  515.     lw        t0, 24(a1)
  516.     lw        t1, 28(a1)
  517.     sw        t0, 24(a2)
  518.     sw        t1, 28(a2)
  519.     lw        t0, 32(a1)
  520.     lw        t1, 36(a1)
  521.     sw        t0, 32(a2)
  522.     sw        t1, 36(a2)
  523.     lw        t0, 40(a1)
  524.     lw        t1, 44(a1)
  525.     sw        t0, 40(a2)
  526.     sw        t1, 44(a2)
  527.     lw        t0, 48(a1)
  528.     lw        t1, 52(a1)
  529.     sw        t0, 48(a2)
  530.     sw        t1, 52(a2)
  531.     lw        t0, 56(a1)
  532.     lw        t1, 60(a1)
  533.     sw        t0, 56(a2)
  534.     sw        t1, 60(a2)
  535.     sub        a0, a0, 64
  536.     add        a1, a1, 64
  537.     add        a2, a2, 64
  538.     j        1b
  539.  
  540. /*
  541.  * Do 4 byte copies.
  542.  */
  543. 2:
  544.     sub        t0, a0, 4
  545.     bltz    t0, 3f
  546.     lw        t0, 0(a1)
  547.     sw        t0, 0(a2)
  548.     sub        a0, a0, 4
  549.     add        a1, a1, 4
  550.     add        a2, a2, 4
  551.     j        2b
  552.  
  553. /*
  554.  * Do one byte copies until done.
  555.  */
  556.  
  557. 3:
  558.     beq        a0, zero, 4f
  559.     lb        t0, 0(a1)
  560.     sb        t0, 0(a2)
  561.     sub        a0, a0, 1
  562.     add        a1, a1, 1
  563.     add        a2, a2, 1
  564.     j        3b
  565.  
  566. /* 
  567.  * Return.
  568.  */
  569. 4: 
  570.     li        v0, 0
  571.     j        ra
  572.  
  573. /* 
  574.  * Vm_CopyOut is just like Vm_CopyIn except that it checks to make sure
  575.  * that the destination is in the user area (otherwise this would be a
  576.  * trap door to write to kernel space).
  577.  */
  578.  
  579.     .globl Vm_CopyOut
  580. .ent Vm_CopyOut
  581. Vm_CopyOut:
  582. /*
  583.  * If a2 is < 0 then it is has the sign bit set which means its in the
  584.  * kernel's VAS.
  585.  */
  586.     bltz    a2, 5f
  587.     j        gotArgs
  588.  
  589. /*
  590.  * User address out of range.  Check for a zero byte count before
  591.  * returning an error, though;  there appear to be kernel routines
  592.  * that call Vm_CopyOut with a zero count but bogus other arguments.
  593.  */
  594.  
  595. 5:
  596.     blez    a0, 6f
  597.     lui        v0, 2
  598.     j        ra
  599. 6:  li        v0, 0
  600.     j        ra
  601. .end
  602.  
  603.  
  604. /*
  605.  * ----------------------------------------------------------------------
  606.  *
  607.  * Vm_StringNCopy
  608.  *
  609.  *    Copy the NULL terminated string from *sourcePtr to *destPtr up
  610.  *    numBytes worth of bytes.
  611.  *
  612.  *    void
  613.  *    Vm_StringNCopy(numBytes, sourcePtr, destPtr, bytesCopiedPtr)
  614.  *        register int numBytes;      * The number of bytes to copy *
  615.  *        Address sourcePtr;          * Where to copy from. *
  616.  *        Address destPtr;            * Where to copy to. *
  617.  *        int    *bytesCopiedPtr;    * Number of bytes copied. *
  618.  *
  619.  *    NOTE: The trap handler assumes that this routine does not push anything
  620.  *          onto the stack.  It uses this fact to allow it to return to the
  621.  *          caller of this routine upon an address fault.  If you must push
  622.  *          something onto the stack then you had better go and modify 
  623.  *          "CallTrapHandler" in asmDefs.h appropriately.
  624.  *
  625.  * Results:
  626.  *    Normally returns SUCCESS.  If a non-recoverable bus error occurs,
  627.  *    then the trap handler fakes up a SYS_ARG_NO_ACCESS return from
  628.  *    this procedure.
  629.  *
  630.  * Side effects:
  631.  *    The area that destPtr points to is modified and *bytesCopiedPtr 
  632.  *    contains the number of bytes copied.
  633.  *
  634.  * ----------------------------------------------------------------------
  635.  */
  636.     .globl  Vm_StringNCopy
  637. Vm_StringNCopy:
  638.     add        t2, a0, 0        # Save the number of bytes
  639. 1:
  640.     lb        t0, 0(a1)
  641.     sb        t0, 0(a2)
  642.     beq        t0, zero, 2f
  643.     add        a1, a1, 1
  644.     add        a2, a2, 1
  645.     sub        a0, a0, 1
  646.     bne        a0, zero, 1b
  647. 2: 
  648.     sub        a0, t2, a0
  649.     sw        a0, 0(a3)
  650.     li        v0, 0
  651.     j        ra
  652.  
  653.  
  654. /*
  655.  * ----------------------------------------------------------------------
  656.  *
  657.  * Vm_TouchPages --
  658.  *
  659.  *    Touch the range of pages.
  660.  *
  661.  *    void
  662.  *    Vm_TouchPages(firstPage, numPages)
  663.  *        int    firstPage;    * First page to touch. *
  664.  *        int    numPages;    * Number of pages to touch. *
  665.  *
  666.  *    NOTE: The trap handler assumes that this routine does not push anything
  667.  *          onto the stack.  It uses this fact to allow it to return to the
  668.  *          caller of this routine upon an address fault.
  669.  *
  670.  * Results:
  671.  *    Returns SUCCESS if were able to touch the page (which is almost
  672.  *    always).  If a bus error (other than a page fault) occurred while 
  673.  *    reading user memory, then SYS_ARG_NO_ACCESS is returned (this return
  674.  *    occurs from the trap handler, rather than from this procedure).
  675.  *
  676.  * Side effects:
  677.  *    None.
  678.  *
  679.  * ----------------------------------------------------------------------
  680.  */
  681.     .globl Vm_TouchPages
  682. Vm_TouchPages:
  683.     sll        a0, a0, VMMACH_PAGE_SHIFT
  684. 1:
  685.     beq        a1, zero, 2f
  686.     lw        t0, 0(a0)
  687.     sub        a1, a1, 1
  688.     add        a0, a0, VMMACH_PAGE_SIZE
  689.     j        1b
  690. 2:
  691.     j        ra
  692.  
  693.     .globl VmMachCopyEnd
  694. VmMachCopyEnd:
  695.  
  696. /*----------------------------------------------------------------------------
  697.  *
  698.  * VmMach_UTLBMiss --
  699.  *
  700.  *    Handle a user TLB miss.
  701.  *
  702.  *
  703.  * Results:
  704.  *         None.
  705.  *
  706.  * Side effects:
  707.  *    None.
  708.  *
  709.  *----------------------------------------------------------------------------
  710.  */
  711.     .globl VmMach_UTLBMiss
  712.     .ent VmMach_UTLBMiss
  713. VmMach_UTLBMiss:
  714. .set noat
  715. .set noreorder
  716.     mfc0    k0, VMMACH_TLB_HI            # Get the high val.
  717.     lui        k1, 0x8000            
  718.     sw        AT, VMMACH_SAVED_AT_OFFSET(k1)
  719. #ifndef NO_COUNTERS
  720.     lw        AT, VMMACH_UTLB_COUNT_OFFSET(k1)
  721.     nop    
  722.     add        AT, AT, 1
  723.     sw        AT, VMMACH_UTLB_COUNT_OFFSET(k1)
  724. #endif
  725.  
  726. /*
  727.  * Make the hash key.
  728.  */
  729.     srl        k1, k0, VMMACH_PAGE_HASH_SHIFT
  730.     sll        AT, k0, VMMACH_PID_HASH_SHIFT
  731.     xor        k1, k1, AT
  732. .set at
  733.     and        k1, k1, VMMACH_HASH_MASK
  734. .set noat
  735. /*
  736.  * Load the hash table key.
  737.  */
  738.     la        AT, vmMachTLBHashTable
  739.     add        AT, k1, AT
  740.     lw        k1, VMMACH_HASH_KEY_OFFSET(AT)
  741.     nop
  742.  
  743. /*
  744.  * Check for match.
  745.  */
  746.     beq        k1, k0, 1f
  747.     lw        k1, VMMACH_LOW_REG_OFFSET(AT)
  748.     j        SlowUTLBFault
  749. /*
  750.  * We have a match.  Restore AT and write the TLB entry.
  751.  */
  752. 1:
  753.     lui        AT, 0x8000
  754.     mtc0    k1, VMMACH_TLB_LOW
  755.     mfc0    k0, MACH_COP_0_EXC_PC
  756.     tlbwr
  757. #ifndef NO_COUNTERS
  758.     lw        k1, VMMACH_UTLB_HIT_OFFSET(AT)
  759.     nop
  760.     add        k1, k1, 1
  761.     sw        k1, VMMACH_UTLB_HIT_OFFSET(AT)
  762. #endif
  763.     lw        AT, VMMACH_SAVED_AT_OFFSET(AT)
  764.     j        k0
  765.     rfe
  766.     .end VmMach_UTLBMiss
  767.  
  768.     .globl VmMach_EndUTLBMiss
  769. VmMach_EndUTLBMiss:
  770. .set reorder
  771.  
  772. /*
  773.  * We couldn't find a TLB entry.  Find out what mode we came from and call
  774.  * the appropriate handler.
  775.  */
  776. SlowUTLBFault:
  777.     lui        AT, 0x8000
  778.     lw        AT, VMMACH_SAVED_AT_OFFSET(AT)
  779. .set reorder
  780.     mfc0    k0, MACH_COP_0_STATUS_REG
  781.     nop
  782.     and        k0, k0, MACH_SR_KU_PREV
  783.     bne        k0, zero, 1f
  784.     j        Mach_KernGenException
  785. 1:  j        Mach_UserGenException
  786.  
  787. .set at
  788.  
  789. /*----------------------------------------------------------------------------
  790.  *
  791.  * VmMach_KernTLBException --
  792.  *
  793.  *    Handle a kernel TLB fault.
  794.  *
  795.  * Results:
  796.  *         None.
  797.  *
  798.  * Side effects:
  799.  *    None.
  800.  *
  801.  *----------------------------------------------------------------------------
  802.  */
  803.     .globl VmMach_KernTLBException
  804.     .ent VmMach_KernTLBException, 0
  805. VmMach_KernTLBException:
  806. .set noreorder
  807. .set noat
  808.     mfc0    k0, MACH_COP_0_BAD_VADDR    # Get the faulting address
  809.     add        k1, sp, zero
  810.     srl        k1, k1, VMMACH_PAGE_SHIFT
  811.     srl        k0, k0, VMMACH_PAGE_SHIFT
  812.     bne        k0, k1, 1f
  813.     nop
  814.     jal        PrintError
  815.     nop
  816.  
  817. 1:
  818.     mfc0    k0, MACH_COP_0_BAD_VADDR    # Get the faulting address
  819.     li        k1, VMMACH_VIRT_CACHED_START    # Get the lower bound
  820.     sltu    k1, k0, k1            # Compare to the lower bound
  821.     bne        k1, zero, KernGenException    #    and take a normal exception
  822.     nop                        #    if we are lower
  823.     li        k1, MACH_KERN_END        # Get the upper bound
  824.     sltu    k1, k0, k1            # Compare to the upper bound
  825.     beq        k1, zero, KernGenException    #    and take a normal exception
  826.                         #    if we are higher.
  827.     srl        k0, VMMACH_PAGE_SHIFT        # Get the virtual page number.
  828.     li        k1, VMMACH_VIRT_CACHED_START_PAGE
  829.     subu    k0, k0, k1
  830.     lw        k1, vmMach_KernelTLBMap        # Get to map that contains
  831.                         #     the TLB entry.
  832.     sll        k0, k0, 2            # Each entry is four bytes
  833.     add        k0, k0, k1            # Get pointer to entry.
  834.     lw        k0, 0(k0)            # Get entry
  835.     nop
  836.     beq        k0, zero, KernGenException    # If entry is zero then take
  837.                         #    a normal exception.
  838.     mtc0    k0, VMMACH_TLB_LOW        # Set the low entry.
  839.     mfc0    k1, MACH_COP_0_EXC_PC        # Get the exception PC
  840.     tlbwr                    # Write the entry out.
  841.     j        k1
  842.     rfe
  843.  
  844. KernGenException:
  845.     j        Mach_KernGenException
  846.     nop
  847.  
  848. .end VmMach_KernTLBException
  849. .set at
  850. .set reorder
  851.  
  852. /*----------------------------------------------------------------------------
  853.  *
  854.  * VmMach_TLBModException --
  855.  *
  856.  *    Handle a modified exception.
  857.  *
  858.  * Results:
  859.  *         None.
  860.  *
  861.  * Side effects:
  862.  *    None.
  863.  *
  864.  *----------------------------------------------------------------------------
  865.  */
  866.     .globl VmMach_TLBModException
  867.     .ent VmMach_TLBModException, 0
  868. VmMach_TLBModException:
  869. .set noat
  870. .set noreorder
  871.     mfc0    k0, VMMACH_TLB_HI            # Get the high val.
  872.     lui        k1, 0x8000
  873.     sw        AT, VMMACH_SAVED_AT_OFFSET(k1)
  874. #ifndef NO_COUNTERS
  875.     lw        AT, VMMACH_MOD_COUNT_OFFSET(k1)
  876.     nop    
  877.     add        AT, AT, 1
  878.     sw        AT, VMMACH_MOD_COUNT_OFFSET(k1)
  879. #endif
  880.  
  881. /*
  882.  * Make the hash key.
  883.  */
  884.     srl        k1, k0, VMMACH_PAGE_HASH_SHIFT
  885.     sll        AT, k0, VMMACH_PID_HASH_SHIFT
  886.     xor        k1, k1, AT
  887. .set at
  888.     and        k1, k1, VMMACH_HASH_MASK
  889. .set noat
  890. /*
  891.  * Load the hash table key.
  892.  */
  893.     la        AT, vmMachTLBHashTable
  894.     add        AT, k1, AT
  895.     lw        k1, VMMACH_HASH_KEY_OFFSET(AT)
  896.     nop
  897.  
  898. /*
  899.  * Check for match.
  900.  */
  901.     beq        k1, k0, 1f
  902.     nop
  903.     j        SlowModFault
  904.     nop
  905. /*
  906.  * We have a match.  See if we can write this page.
  907.  */
  908. 1:  
  909. #ifndef NO_COUNTERS
  910.     lui        k0, 0x8000
  911.     lw        k1, VMMACH_MOD_HIT_OFFSET(k0)
  912.     nop
  913.     add        k1, k1, 1
  914.     sw        k1, VMMACH_MOD_HIT_OFFSET(k0)
  915. #endif
  916.  
  917.     lw        k1, VMMACH_LOW_REG_OFFSET(AT)
  918.     nop
  919.     and        k0, k1, VMMACH_TLB_ENTRY_WRITEABLE
  920.     beq        k0, zero, SlowModFault
  921.     nop
  922. /*
  923.  * Find the entry in the TLB.  It has to be there since we took a mod fault
  924.  * on it.  While were at it set the mod bit in the hash table entry.
  925.  */
  926.     tlbp
  927.     mfc0    k0, VMMACH_TLB_INDEX
  928.     or        k1, k1, VMMACH_TLB_MOD_BIT
  929.     sw        k1, VMMACH_LOW_REG_OFFSET(AT)
  930.     bltz    k0, 1f
  931.     nop
  932. /*
  933.  * Write the TLB.
  934.  */
  935.     mtc0    k1, VMMACH_TLB_LOW
  936.     nop
  937.     tlbwi
  938. /*
  939.  * Set the modified bit in the physical page array.
  940.  */
  941. .set at
  942.     lw        k0, vmMachPhysPageArr
  943.     srl        k1, k1, VMMACH_TLB_PHYS_PAGE_SHIFT
  944.     sll        k1, k1, 2
  945.     add        k0, k0, k1
  946.     lw        k1, 0(k0)
  947.     nop
  948.     or        k1, k1, 4
  949.     sw        k1, 0(k0)
  950. .set noat
  951. /* 
  952.  * Restore AT and return.
  953.  */
  954.     mfc0    k0, MACH_COP_0_EXC_PC
  955.     lui        AT, 0x8000
  956.     lw        AT, VMMACH_SAVED_AT_OFFSET(AT)
  957.     j        k0
  958.     rfe
  959. 1:
  960.     break    0
  961. .set reorder
  962.  
  963. /*
  964.  * We couldn't find a TLB entry.  Find out what mode we came from and call
  965.  * the appropriate handler.
  966.  */
  967. SlowModFault:
  968.     lui        AT, 0x8000
  969.     lw        AT, VMMACH_SAVED_AT_OFFSET(AT)
  970. .set reorder
  971.     mfc0    k0, MACH_COP_0_STATUS_REG
  972.     nop
  973.     and        k0, k0, MACH_SR_KU_PREV
  974.     bne        k0, zero, 1f
  975.     j        Mach_KernGenException
  976. 1:  j        Mach_UserGenException
  977.  
  978. .end VmMach_TLBModException
  979. .set at
  980.  
  981.